package org.jeecgframework.core.common.dao.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.internal.CriteriaImpl;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.persister.entity.AbstractEntityPersister;
import org.hibernate.type.Type;
import org.jeecgframework.core.annotation.JeecgEntityTitle;
import org.jeecgframework.core.common.dao.IGenericBaseCommonDao;
import org.jeecgframework.core.common.dao.jdbc.JdbcDao;
import org.jeecgframework.core.common.exception.BusinessException;
import org.jeecgframework.core.common.hibernate.qbc.CriteriaQuery;
import org.jeecgframework.core.common.hibernate.qbc.DetachedCriteriaUtil;
import org.jeecgframework.core.common.hibernate.qbc.HqlQuery;
import org.jeecgframework.core.common.hibernate.qbc.PageList;
import org.jeecgframework.core.common.hibernate.qbc.PagerUtil;
import org.jeecgframework.core.common.model.common.DBTable;
import org.jeecgframework.core.common.model.json.DataGridReturn;
import org.jeecgframework.core.util.MyBeanUtils;
import org.jeecgframework.core.util.StringUtil;
import org.jeecgframework.core.util.ToEntityUtil;
import org.jeecgframework.core.util.oConvertUtils;
import org.jeecgframework.tag.vo.datatable.DataTableReturn;
import org.jeecgframework.tag.vo.datatable.SortDirection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.util.Assert;


/**
 * 类描述： DAO层泛型基类
 * <p>
 * admin
 *
 * @date： 日期：2012-12-7 时间：上午10:16:48
 * @param <T>
 * @param <PK>
 * @version 1.0
 */

/**
 * Demo class
 *
 * @author admin
 * @date 2016/10/31
 */
@SuppressWarnings("hiding")
public abstract class GenericBaseCommonDao<T, PK extends Serializable>
        implements IGenericBaseCommonDao {
    /**
     * 初始化Log4j的一个实例
     */
    private static final Logger logger = Logger.getLogger(GenericBaseCommonDao.class);
    /**
     * 注入一个sessionFactory属性,并注入到父类(HibernateDaoSupport)
     * **/
    @Autowired
    @Qualifier("sessionFactory")
    private SessionFactory sessionFactory;

    @Override
    public Session getSession() {
        // 事务必须是开启的(Required)，否则获取不到
        return sessionFactory.getCurrentSession();
    }

    /**
     * 获得该类的属性和类型
     *
     * @param entityName
     *            注解的实体类
     */
    private <T> void getProperty(Class entityName) {
        ClassMetadata cm = sessionFactory.getClassMetadata(entityName);
        String[] str = cm.getPropertyNames(); // 获得该类所有的属性名称
        for (int i = 0; i < str.length; i++) {
            String property = str[i];
            String type = cm.getPropertyType(property).getName(); // 获得该名称的类型
            org.jeecgframework.core.util.LogUtil.info(property + "---&gt;" + type);
        }
    }

    /**
     * 获取所有数据表
     *
     * @return
     */
    @Override
    public List<DBTable> getAllDbTableName() {
        List<DBTable> resultList = new ArrayList<DBTable>();
        SessionFactory factory = getSession().getSessionFactory();
        Map<String, ClassMetadata> metaMap = factory.getAllClassMetadata();
        for (String key : (Set<String>) metaMap.keySet()) {
            DBTable dbTable = new DBTable();
            AbstractEntityPersister classMetadata = (AbstractEntityPersister) metaMap
                    .get(key);
            dbTable.setTableName(classMetadata.getTableName());
            dbTable.setEntityName(classMetadata.getEntityName());
            Class<?> c;
            try {
                c = Class.forName(key);
                JeecgEntityTitle t = c.getAnnotation(JeecgEntityTitle.class);
                dbTable.setTableTitle(t != null ? t.name() : "");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            resultList.add(dbTable);
        }
        return resultList;
    }

    /**
     * 获取所有数据表
     *
     * @return
     */
    @Override
    public Integer getAllDbTableSize() {
        SessionFactory factory = getSession().getSessionFactory();
        Map<String, ClassMetadata> metaMap = factory.getAllClassMetadata();
        return metaMap.size();
    }

    /**
     * 根据实体名字获取唯一记录
     *
     * @param propertyName
     * @param value
     * @return
     */
    @Override
    public <T> T findUniqueByProperty(Class<T> entityClass,
                                      String propertyName, Object value) {
        Assert.hasText(propertyName);
        return (T) createCriteria(entityClass,
                Restrictions.eq(propertyName, value)).uniqueResult();
    }

    /**
     * 按属性查找对象列表.
     */
    @Override
    public <T> List<T> findByProperty(Class<T> entityClass,
                                      String propertyName, Object value) {
        Assert.hasText(propertyName);
        return (List<T>) createCriteria(entityClass,
                Restrictions.eq(propertyName, value)).list();
    }

    /**
     * 根据传入的实体持久化对象
     */
    @Override
    public <T> Serializable save(T entity) {
        try {
            Serializable id = getSession().save(entity);
            //getSession().flush();
            if (logger.isDebugEnabled()) {
                logger.debug("保存实体成功," + entity.getClass().getName());
            }
            return id;
        } catch (RuntimeException e) {
            logger.error("保存实体异常", e);
            throw e;
        }

    }

    /**
     * 批量保存数据
     *
     * @param <T>
     * @param entitys
     *            要持久化的临时实体对象集合
     */
    @Override
    public <T> void batchSave(List<T> entitys) {
        for (int i = 0; i < entitys.size(); i++) {
            getSession().save(entitys.get(i));
            if (i % 1000 == 0) {
                // 1000个对象批量写入数据库，后才清理缓存
                getSession().flush();
                getSession().clear();
            }
        }
        //最后页面的数据，进行提交手工清理
        getSession().flush();
        getSession().clear();
    }

    /**
     * 根据传入的实体添加或更新对象
     *
     * @param <T>
     *
     * @param entity
     */

    @Override
    public <T> void saveOrUpdate(T entity) {
        try {
            getSession().saveOrUpdate(entity);
            //getSession().flush();
            if (logger.isDebugEnabled()) {
                logger.debug("添加或更新成功," + entity.getClass().getName());
            }
        } catch (RuntimeException e) {
            logger.error("添加或更新异常", e);
            throw e;
        }
    }

    /**
     * 根据传入的实体删除对象
     */
    @Override
    public <T> void delete(T entity) {
        try {
            getSession().delete(entity);
            //getSession().flush();
            if (logger.isDebugEnabled()) {
                logger.debug("删除成功," + entity.getClass().getName());
            }
        } catch (RuntimeException e) {
            logger.error("删除异常", e);
            throw e;
        }
    }

    /**
     * 根据主键删除指定的实体
     *
     * @param <T>
     * @param id
     */
    @Override
    public <T> void deleteEntityById(Class entityName, Serializable id) {
        delete(get(entityName, id));
        //getSession().flush();
    }

    /**
     * 删除全部的实体
     *
     * @param <T>
     *
     * @param entitys
     */
    @Override
    public <T> void deleteAllEntitie(Collection<T> entitys) {
        for (Object entity : entitys) {
            getSession().delete(entity);
            //getSession().flush();
        }
    }

    /**
     * 根据Id获取对象。
     */
    @Override
    public <T> T get(Class<T> entityClass, final Serializable id) {

        return (T) getSession().get(entityClass, id);

    }

    /**
     * 根据主键获取实体并加锁。
     *
     * @param <T>
     * @param entityName
     * @param id
     * @return
     */
    @Override
    public <T> T getEntity(Class entityName, Serializable id) {

        T t = (T) getSession().get(entityName, id);
        if (t != null) {
            //getSession().flush();
        }
        return t;
    }

    /**
     * 更新指定的实体
     *
     * @param <T>
     * @param pojo
     */
    @Override
    public <T> void updateEntitie(T pojo) {
        getSession().update(pojo);
        //getSession().flush();
    }

    /**
     * 更新指定的实体
     *
     * @param <T>
     * @param id
     */
    public <T> void updateEntitie(String className, Object id) {
        getSession().update(className, id);
        //getSession().flush();
    }

    /**
     * 根据主键更新实体
     */
    @Override
    public <T> void updateEntityById(Class entityName, Serializable id) {
        updateEntitie(get(entityName, id));
    }

    /**
     * 通过hql 查询语句查找对象
     *
     * @param query
     * @return
     */
    @Override
    public List<T> findByQueryString(final String query) {

        Query queryObject = getSession().createQuery(query);
        List<T> list = queryObject.list();
//		if (list.size() > 0) {
        //getSession().flush();
//		}
        return list;

    }

    /**
     * 通过hql查询唯一对象
     *
     * @param <T>
     * @param hql
     * @return
     */
    @Override
    public <T> T singleResult(String hql) {
        T t = null;
        Query queryObject = getSession().createQuery(hql);
        List<T> list = queryObject.list();
        if (list.size() == 1) {
            //getSession().flush();
            t = list.get(0);
        } else if (list.size() > 0) {
            throw new BusinessException("查询结果数:" + list.size() + "大于1");
        }
        return t;
    }

    /**
     * 通过hql 查询语句查找HashMap对象
     *
     * @param hql
     * @return
     */
    @Override
    public Map<Object, Object> getHashMapbyQuery(String hql) {

        Query query = getSession().createQuery(hql);
        List list = query.list();
        Map<Object, Object> map = new HashMap<Object, Object>(1024);
        for (Iterator iterator = list.iterator(); iterator.hasNext(); ) {
            Object[] tm = (Object[]) iterator.next();
            map.put(tm[0].toString(), tm[1].toString());
        }
        return map;

    }

    /**
     * 通过sql更新记录
     *
     * @param query
     * @return
     */
    @Override
    public int updateBySqlString(final String query) {

        Query querys = getSession().createSQLQuery(query);
        return querys.executeUpdate();
    }

    /**
     * 通过sql查询语句查找对象
     *
     * @param sql
     * @return
     */
    @Override
    public List<T> findListbySql(final String sql) {
        Query querys = getSession().createSQLQuery(sql);
        return querys.list();
    }

    /**
     * 创建Criteria对象，有排序功能。
     *
     * @param <T>
     * @param entityClass
     * @param isAsc
     * @param criterions
     * @return
     */
    private <T> Criteria createCriteria(Class<T> entityClass, boolean isAsc,
                                        Criterion... criterions) {
        Criteria criteria = createCriteria(entityClass, criterions);
        if (isAsc) {
            criteria.addOrder(Order.asc("asc"));
        } else {
            criteria.addOrder(Order.desc("desc"));
        }
        return criteria;
    }

    /**
     * 创建Criteria对象带属性比较
     *
     * @param <T>
     * @param entityClass
     * @param criterions
     * @return
     */
    private <T> Criteria createCriteria(Class<T> entityClass,
                                        Criterion... criterions) {
        Criteria criteria = getSession().createCriteria(entityClass);
        for (Criterion c : criterions) {
            criteria.add(c);
        }
        return criteria;
    }

    @Override
    public <T> List<T> loadAll(final Class<T> entityClass) {
        Criteria criteria = createCriteria(entityClass);
        return criteria.list();
    }

    /**
     * 创建单一Criteria对象
     *
     * @param <T>
     * @param entityClass
     * @return
     */
    private <T> Criteria createCriteria(Class<T> entityClass) {
        Criteria criteria = getSession().createCriteria(entityClass);
        return criteria;
    }

    /**
     * 根据属性名和属性值查询. 有排序
     *
     * @param <T>
     * @param entityClass
     * @param propertyName
     * @param value
     * @param isAsc
     * @return
     */
    @Override
    public <T> List<T> findByPropertyisOrder(Class<T> entityClass,
                                             String propertyName, Object value, boolean isAsc) {
        Assert.hasText(propertyName);
        return createCriteria(entityClass, isAsc,
                Restrictions.eq(propertyName, value)).list();
    }

    /**
     * 根据属性名和属性值 查询 且要求对象唯一.
     *
     * @return 符合条件的唯一对象.
     */
    public <T> T findUniqueBy(Class<T> entityClass, String propertyName,
                              Object value) {
        Assert.hasText(propertyName);
        return (T) createCriteria(entityClass,
                Restrictions.eq(propertyName, value)).uniqueResult();
    }

    /**
     * 根据查询条件与参数列表创建Query对象
     *
     * @param session
     *            Hibernate会话
     * @param hql
     *            HQL语句
     * @param objects
     *            参数列表
     * @return Query对象
     */
    public Query createQuery(Session session, String hql, Object... objects) {
        Query query = session.createQuery(hql);
        if (objects != null) {
            for (int i = 0; i < objects.length; i++) {
                query.setParameter(i, objects[i]);
            }
        }
        return query;
    }

    /**
     * 批量插入实体
     *
     * @param entityList
     * @return
     */
    public <T> int batchInsertsEntitie(List<T> entityList) {
        int num = 0;
        for (int i = 0; i < entityList.size(); i++) {
            save(entityList.get(i));
            num++;
        }
        return num;
    }

    /**
     * 根据实体名返回全部对象
     *
     * @param <T>
     * @param hql
     * @param size
     * @return
     */
    /**
     * 使用占位符的方式填充值 请注意：like对应的值格式："%"+username+"%" Hibernate Query
     *
     * @param hql
     * @param values
     *            占位符号?对应的值，顺序必须一一对应 可以为空对象数组，但是不能为null
     * @return 2008-07-19 add by liuyang
     */
    public List<T> executeQuery(final String hql, final Object[] values) {
        Query query = getSession().createQuery(hql);
        // query.setCacheable(true);
        for (int i = 0; values != null && i < values.length; i++) {
            query.setParameter(i, values[i]);
        }

        return query.list();

    }

    /**
     * 根据实体模版查找
     *
     * @param entityName
     * @param exampleEntity
     * @return
     */

    @Override
    public List findByExample(final String entityName,
                              final Object exampleEntity) {
        Assert.notNull(exampleEntity, "Example entity must not be null");
        Criteria executableCriteria = (entityName != null ? getSession()
                .createCriteria(entityName) : getSession().createCriteria(
                exampleEntity.getClass()));
        executableCriteria.add(Example.create(exampleEntity));
        return executableCriteria.list();
    }

    // 使用指定的检索标准获取满足标准的记录数
    public Integer getRowCount(DetachedCriteria criteria) {
        return oConvertUtils.getInt(((Criteria) criteria
                .setProjection(Projections.rowCount())).uniqueResult(), 0);
    }

    /**
     * 调用存储过程
     */
    public void callableStatementByName(String proc) {
    }

    /**
     * 查询指定实体的总记录数
     *
     * @param clazz
     * @return
     */
    public int getCount(Class<T> clazz) {

        int count = DataAccessUtils.intResult(getSession().createQuery(
                "select count(*) from " + clazz.getName()).list());
        return count;
    }

    /**
     * 获取分页记录CriteriaQuery 老方法final int allCounts =
     * oConvertUtils.getInt(criteria
     * .setProjection(Projections.rowCount()).uniqueResult(), 0);
     *
     * @param cq
     * @param isOffset
     * @return
     */
    @Override
    public PageList getPageList(final CriteriaQuery cq, final boolean isOffset) {

        Criteria criteria = cq.getDetachedCriteria().getExecutableCriteria(
                getSession());
        CriteriaImpl impl = (CriteriaImpl) criteria;
        // 先把Projection和OrderBy条件取出来,清空两者来执行Count操作
        Projection projection = impl.getProjection();
        final int allCounts = ((Long) criteria.setProjection(
                Projections.rowCount()).uniqueResult()).intValue();
        criteria.setProjection(projection);
        if (projection == null) {
            criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
        }

        // 判断是否有排序字段
        if (cq.getOrdermap() != null) {
            cq.setOrder(cq.getOrdermap());
        }
        int pageSize = cq.getPageSize();// 每页显示数
        int curPageNO = PagerUtil.getcurPageNo(allCounts, cq.getCurPage(),
                pageSize);// 当前页
        int offset = PagerUtil.getOffset(allCounts, curPageNO, pageSize);
        String toolBar = "";
        if (isOffset) {// 是否分页
            criteria.setFirstResult(offset);
            criteria.setMaxResults(cq.getPageSize());
            if (cq.getIsUseimage() == 1) {
                toolBar = PagerUtil.getBar(cq.getMyAction(), cq.getMyForm(),
                        allCounts, curPageNO, pageSize, cq.getMap());
            } else {
                toolBar = PagerUtil.getBar(cq.getMyAction(), allCounts,
                        curPageNO, pageSize, cq.getMap());
            }
        } else {
            pageSize = allCounts;
        }
        return new PageList(criteria.list(), toolBar, offset, curPageNO,
                allCounts);
    }

    /**
     * 返回JQUERY datatables DataTableReturn模型对象
     */
    @Override
    public DataTableReturn getDataTableReturn(final CriteriaQuery cq,
                                              final boolean isOffset) {

        Criteria criteria = cq.getDetachedCriteria().getExecutableCriteria(
                getSession());
        CriteriaImpl impl = (CriteriaImpl) criteria;
        // 先把Projection和OrderBy条件取出来,清空两者来执行Count操作
        Projection projection = impl.getProjection();
        final int allCounts = ((Long) criteria.setProjection(
                Projections.rowCount()).uniqueResult()).intValue();
        criteria.setProjection(projection);
        if (projection == null) {
            criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
        }

        // 判断是否有排序字段
        if (cq.getOrdermap() != null) {
            cq.setOrder(cq.getOrdermap());
        }
        int pageSize = cq.getPageSize();// 每页显示数
        int curPageNO = PagerUtil.getcurPageNo(allCounts, cq.getCurPage(),
                pageSize);// 当前页
        int offset = PagerUtil.getOffset(allCounts, curPageNO, pageSize);
        if (isOffset) {// 是否分页
            criteria.setFirstResult(offset);
            criteria.setMaxResults(cq.getPageSize());
        } else {
            pageSize = allCounts;
        }
        DetachedCriteriaUtil.selectColumn(cq.getDetachedCriteria(), cq.getField().split(","), cq.getEntityClass(), false);
        return new DataTableReturn(allCounts, allCounts, cq.getDataTables().getEcho(), criteria.list());
    }

    /**
     * 返回easyui datagrid DataGridReturn模型对象
     */
    @Override
    public DataGridReturn getDataGridReturn(final CriteriaQuery cq,
                                            final boolean isOffset) {
        Criteria criteria = cq.getDetachedCriteria().getExecutableCriteria(getSession());
        CriteriaImpl impl = (CriteriaImpl) criteria;
        // 先把Projection和OrderBy条件取出来,清空两者来执行Count操作
        Projection projection = impl.getProjection();
        final int allCounts = ((Long) criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue();
        criteria.setProjection(projection);
        if (projection == null) {
            criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
        }

        if (StringUtils.isNotBlank(cq.getDataGrid().getSort())) {
            String[] sortArr = cq.getDataGrid().getSort().split(",");
            String[] orderArr = cq.getDataGrid().getOrder().split(",");
            if (sortArr.length == orderArr.length) {
                for (int i = 0; i < sortArr.length; i++) {
//					cq.addOrder(sortArr[i], SortDirection.toEnum(orderArr[i]));
                    if (SortDirection.asc.equals(SortDirection.toEnum(orderArr[i]))) {
                        cq.getDetachedCriteria().addOrder(Order.asc(sortArr[i]));
                    } else {
                        cq.getDetachedCriteria().addOrder(Order.desc(sortArr[i]));
                    }
                }
            } else if (orderArr.length > 0) {
                for (int i = 0; i < sortArr.length; i++) {
//					cq.addOrder(sortArr[i], SortDirection.toEnum(orderArr[0]));
                    if (SortDirection.asc.equals(SortDirection.toEnum(orderArr[0]))) {
                        cq.getDetachedCriteria().addOrder(Order.asc(sortArr[i]));
                    } else {
                        cq.getDetachedCriteria().addOrder(Order.desc(sortArr[i]));
                    }
                }
            }
        }


        // 判断是否有排序字段
//		if (!cq.getOrdermap().isEmpty()) {
//			cq.setOrder(cq.getOrdermap());
//		}
        int pageSize = cq.getPageSize();// 每页显示数
        int curPageNO = PagerUtil.getcurPageNo(allCounts, cq.getCurPage(), pageSize);// 当前页
        int offset = PagerUtil.getOffset(allCounts, curPageNO, pageSize);
        if (isOffset) {// 是否分页
            criteria.setFirstResult(offset);
            criteria.setMaxResults(cq.getPageSize());
        } else {
            pageSize = allCounts;
        }
        // DetachedCriteriaUtil.selectColumn(cq.getDetachedCriteria(),
        // cq.getField().split(","), cq.getClass1(), false);
        List list = criteria.list();
        cq.getDataGrid().setResults(list);
        cq.getDataGrid().setTotal(allCounts);
        return new DataGridReturn(allCounts, list);
    }

    /**
     * 获取分页记录SqlQuery
     *
     * @param hqlQuery
     * @param isToEntity
     * @return
     */
    @Override
    @SuppressWarnings("unchecked")
    public PageList getPageListBySql(final HqlQuery hqlQuery,
                                     final boolean isToEntity) {

        Query query = getSession().createSQLQuery(hqlQuery.getQueryString());

        // query.setParameters(hqlQuery.getParam(), (Type[])
        // hqlQuery.getTypes());
        int allCounts = query.list().size();
        int curPageNO = hqlQuery.getCurPage();
        int offset = PagerUtil.getOffset(allCounts, curPageNO,
                hqlQuery.getPageSize());
        query.setFirstResult(offset);
        query.setMaxResults(hqlQuery.getPageSize());
        List list = null;
        if (isToEntity) {
            list = ToEntityUtil.toEntityList(query.list(),
                    hqlQuery.getClass1(), hqlQuery.getDataGrid().getField()
                            .split(","));
        } else {
            list = query.list();
        }
        return new PageList(hqlQuery, list, offset, curPageNO, allCounts);
    }

    /**
     * 获取分页记录HqlQuery
     *
     * @param hqlQuery
     * @param needParameter
     * @return
     */
    @Override
    @SuppressWarnings("unchecked")
    public PageList getPageList(final HqlQuery hqlQuery,
                                final boolean needParameter) {

        Query query = getSession().createQuery(hqlQuery.getQueryString());
        if (needParameter) {
            query.setParameters(hqlQuery.getParam(),
                    (Type[]) hqlQuery.getTypes());
        }
        int allCounts = query.list().size();
        int curPageNO = hqlQuery.getCurPage();
        int offset = PagerUtil.getOffset(allCounts, curPageNO,
                hqlQuery.getPageSize());
        String toolBar = PagerUtil.getBar(hqlQuery.getMyaction(), allCounts,
                curPageNO, hqlQuery.getPageSize(), hqlQuery.getMap());
        query.setFirstResult(offset);
        query.setMaxResults(hqlQuery.getPageSize());
        return new PageList(query.list(), toolBar, offset, curPageNO, allCounts);
    }

    /**
     * 根据CriteriaQuery获取List
     *
     * @param cq
     * @param ispage
     * @return
     */
    @Override
    @SuppressWarnings("unchecked")
    public List<T> getListByCriteriaQuery(final CriteriaQuery cq, Boolean ispage) {
        Criteria criteria = cq.getDetachedCriteria().getExecutableCriteria(
                getSession());
        // 判断是否有排序字段
        if (cq.getOrdermap() != null) {
            cq.setOrder(cq.getOrdermap());
        }
        if (ispage) {
            criteria.setFirstResult((cq.getCurPage() - 1) * cq.getPageSize());
            criteria.setMaxResults(cq.getPageSize());
        }
        return criteria.list();

    }

    @Autowired
    @Qualifier("jdbcTemplate")
    private JdbcTemplate jdbcTemplate;

    @Autowired
    @Qualifier("namedParameterJdbcTemplate")
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    /**
     * 使用指定的检索标准检索数据并分页返回数据
     */
    @Override
    public List<Map<String, Object>> findForJdbc(String sql, int page, int rows) {
        // 封装分页SQL
        sql = JdbcDao.jeecgCreatePageSql(sql, page, rows);
        return this.jdbcTemplate.queryForList(sql);
    }

    /**
     * 使用指定的检索标准检索数据并分页返回数据
     *
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    @Override
    public <T> List<T> findObjForJdbc(String sql, int page, int rows,
                                      Class<T> clazz) {
        List<T> rsList = new ArrayList<T>();
        // 封装分页SQL
        sql = JdbcDao.jeecgCreatePageSql(sql, page, rows);
        List<Map<String, Object>> mapList = jdbcTemplate.queryForList(sql);

        T po = null;
        for (Map<String, Object> m : mapList) {
            try {
                po = clazz.newInstance();
                MyBeanUtils.copyMap2Bean_Nobig(po, m);
                rsList.add(po);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return rsList;
    }

    /**
     * 使用指定的检索标准检索数据并分页返回数据-采用预处理方式
     *
     * @param sql
     * @param page
     * @param objs
     * @return
     * @throws DataAccessException
     */
    @Override
    public List<Map<String, Object>> findForJdbcParam(String sql, int page,
                                                      int rows, Object... objs) {
        // 封装分页SQL
        sql = JdbcDao.jeecgCreatePageSql(sql, page, rows);
        return this.jdbcTemplate.queryForList(sql, objs);
    }

    /**
     * 使用指定的检索标准检索数据并分页返回数据For JDBC
     */
    @Override
    public Long getCountForJdbc(String sql) {
        return this.jdbcTemplate.queryForObject(sql, Long.class);
    }

    /**
     * 使用指定的检索标准检索数据并分页返回数据For JDBC-采用预处理方式
     *
     */
    @Override
    public Long getCountForJdbcParam(String sql, Object[] objs) {

        return this.jdbcTemplate.queryForObject(sql, objs, Long.class);


    }

    @Override
    public List<Map<String, Object>> findForJdbc(String sql, Object... objs) {
        return this.jdbcTemplate.queryForList(sql, objs);
    }

    @Override
    public Integer executeSql(String sql, List<Object> param) {
        return this.jdbcTemplate.update(sql, param);
    }

    @Override
    public Integer executeSql(String sql, Object... param) {
        return this.jdbcTemplate.update(sql, param);
    }

    @Override
    public Integer executeSql(String sql, Map<String, Object> param) {
        MapSqlParameterSource parameterSource = new MapSqlParameterSource(param);
        return namedParameterJdbcTemplate.update(sql, parameterSource);
    }

    @Override
    public Object executeSqlReturnKey(final String sql, Map<String, Object> param) {
        Object keyValue = null;
        KeyHolder keyHolder = null;
        SqlParameterSource sqlp = new MapSqlParameterSource(param);
        if (StringUtil.isNotEmpty(param.get("id"))) {//表示已经生成过id(UUID),则表示是非序列或数据库自增的形式
            this.namedParameterJdbcTemplate.update(sql, sqlp);
            //--author：zhoujf---start------date:20170216--------for:自定义表单保存数据格sqlserver报错问题
        } else if (StringUtil.isNotEmpty(param.get("ID"))) {//表示已经生成过id(UUID),则表示是非序列或数据库自增的形式
            this.namedParameterJdbcTemplate.update(sql, sqlp);
        } else {//NATIVE or SEQUENCE
            keyHolder = new GeneratedKeyHolder();
            this.namedParameterJdbcTemplate.update(sql, sqlp, keyHolder, new String[]{"id" });
            Number number = keyHolder.getKey();
            if (oConvertUtils.isNotEmpty(number)) {
                keyValue = keyHolder.getKey().longValue();
            }
        }
        return keyValue;
    }

    public Integer countByJdbc(String sql, Object... param) {

        return this.jdbcTemplate.queryForObject(sql, param, Integer.class);


    }

    @Override
    public Map<String, Object> findOneForJdbc(String sql, Object... objs) {
        try {
            return this.jdbcTemplate.queryForMap(sql, objs);
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
    }

    /**
     * 通过hql 查询语句查找对象
     *
     * @param <T>
     * @param hql
     * @return
     */
    @Override
    public <T> List<T> findHql(String hql, Object... param) {
        Query q = getSession().createQuery(hql);
        if (param != null && param.length > 0) {
            for (int i = 0; i < param.length; i++) {
                q.setParameter(i, param[i]);
            }
        }
        return q.list();
    }

    /**
     * 执行HQL语句操作更新
     *
     * @param hql
     * @return
     */
    @Override
    public Integer executeHql(String hql) {
        Query q = getSession().createQuery(hql);
        return q.executeUpdate();
    }

    @Override
    public <T> List<T> pageList(DetachedCriteria dc, int firstResult,
                                int maxResult) {
        Criteria criteria = dc.getExecutableCriteria(getSession());
        criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
        criteria.setFirstResult(firstResult);
        criteria.setMaxResults(maxResult);
        return criteria.list();
    }

    /**
     * 离线查询
     */
    @Override
    public <T> List<T> findByDetached(DetachedCriteria dc) {
        return dc.getExecutableCriteria(getSession()).list();
    }

    /**
     * 调用存储过程
     */
    @Override
    @SuppressWarnings({"unchecked",})
    public <T> List<T> executeProcedure(String executeSql, Object... params) {
        SQLQuery sqlQuery = getSession().createSQLQuery(executeSql);

        for (int i = 0; i < params.length; i++) {
            sqlQuery.setParameter(i, params[i]);
        }

        return sqlQuery.list();
    }

}
